'''
Copyright: 
Descripttion: 
version: 
Author: chengx
Date: 2021-10-15 15:13:40
LastEditors: chengx
LastEditTime: 2022-03-10 14:18:30
'''
import sys
import seaborn as sns
from sklearn.preprocessing import  StandardScaler
import numpy as np  
import matplotlib.pyplot as plt 
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score,f1_score,roc_auc_score
from sklearn.mixture import GaussianMixture
from collections import Counter
from sklearn.metrics import confusion_matrix

def readData(rand):
    x = np.load('./data/AvrData.npy')
    y = np.load('./data/AvrLabel.npy')

    print(x.shape,y.shape)
    x=x[:,26:230]

    import scipy.signal
    x = scipy.signal.savgol_filter(x, 9, 2, deriv=1)  # 一阶导数处理
    x_abnom = x[~(y==0)] # 标签不为0的是异常
    x_nom = x[y==0]

    X_train, X_nom_test = train_test_split(x_nom, train_size = 0.5, random_state = rand)
    X_test = np.concatenate([X_nom_test,x_abnom],axis = 0)
    y_test = np.concatenate([np.zeros(len(X_nom_test)),np.ones(len(x_abnom))])
    print('X_train.shape, X_test.shape,y_test.shape',X_train.shape, X_test.shape, y_test.shape)
    
    return X_train, X_test, y_test,X_nom_test

def preProcess(X_train,X_test): # 数据预处理
    sc = StandardScaler()#去均值和方差归一化
    X_train = sc.fit_transform(X_train) # 先在训练集上拟合fit，找到该part的整体指标，然后进行转换transform
    X_test = sc.transform(X_test) # 对剩余的数据采用上面相同的指标进行transform
    return X_train, X_test

def fitGmm(x_train):
    clf = GaussianMixture(n_components=1)
    # params = {'covariance_type' : ['full', 'tied', 'diag', 'spherical']}

    # clf = GridSearchCV(clf, params, cv=5)
    clf.fit(x_train)
    # print('best',clf.best_params_)
    # clf = clf.best_estimator_

    return clf

def mm(y_pred,y_true,X_nom_test):
    #decision_threshold
    # plt.plot(y_pred)
    # plt.show()
    decision=np.zeros((y_pred.shape[0]))
    index = np.argsort(y_pred)
    # plt.plot(index)
    # plt.show()

    decision[index[0:X_nom_test.shape[0]+2]]=0 #正常的
    decision[index[X_nom_test.shape[0]+2:]]=1
    # plt.plot(decision)
    # plt.show()

    auc = roc_auc_score(y_test, decision)
    print('auc',auc)

    tn, fp, fn, tp = confusion_matrix(y_true, decision).ravel()
    prec = tp / np.maximum(tp + fp, sys.float_info.epsilon)
    recall = tp / np.maximum(tp + fn, sys.float_info.epsilon)
    f1 = 2.0 * prec * recall / np.maximum(prec + recall, sys.float_info.epsilon)
    print('tn,fp,fn,tp',tn,fp,fn,tp)
    print('prec:',prec)
    print('recall:',recall)
    print('f1:',f1)
    return auc,prec,recall,f1


if __name__ == "__main__":
    AC = []
    PC = []
    RC = []
    FC = []
    for i in range(10):
        x_train, x_test, y_test,X_nom_test = readData(i)
        model = fitGmm(x_train)
        errors = -model.score_samples(x_test) #返回加权对数概率，所以指数形式就是gmm模型给出的概率
        y_pred = errors
        auc_score,prec,recall,f1 = mm(y_pred, y_test,X_nom_test)

        AC.append(auc_score)
        PC.append(prec)
        RC.append(recall)
        FC.append(f1)

    print('auc',list(np.round(AC,3)))
    print('precision',list(np.round(PC,3)))
    print('recall',list(np.round(RC,3)))
    print('f1-score',list(np.round(FC,3)))